/*
 * @Descripttion: 向外暴露的表格方法
 * @version: v1.0
 * @Author: 34786
 * @Date: 2020-08-13 14:12:26
 * @LastEditors: 34786
 * @LastEditTime: 2020-08-19 10:55:21
 */

export default {
  methods: {
    /**
     * @name: refreshTable
     * @type: Promise
     * @description: 刷新表格
     * @return {Promise}
     */
    refreshTable() {
      return new Promise((resolve, reject) => {
        let opt = this.opt;
        this.load(
          opt.url,
          opt.param,
          opt.params.pageNumber,
          opt.params.pageSize
        )
          .then(() => {
            resolve();
          })
          .catch(err => {
            reject(err);
          });
      });
    },

    /**
     * @name: createRow
     * @description:
     * @type: Function
     * @param {object} records
     * @return {Promise}
     */
    createRow(records = {}) {
      return this.$refs.editable.createRow(records);
    },

    /**
     * @name: insertRow
     * @description: 往表格指定位置插入临时数据（不支持深层结构）
     * @type: Function
     * @param {object | Array<object>} records: 一行或多行数据
     * @param {Row} row?: null从第一行插入、-1 从最后插入，默认 -1
     * @return {Promise}
     */
    insertRow(records = {}, row = -1) {
      return this.$refs.editable.insertAt(records, row);
    },

    /**
     * @name: insert
     * @description: 从第一行插入一行或多行数据（不支持深层结构）
     * @type: Function
     * @param {object | Array<object>} records?: 一行或多行数据
     * @return {Promise}
     */
    insert(records) {
      return this.$refs.editable.insert(records);
    },

    /**
     * @name: revertData
     * @description: 还原指定行 row 或者整个表格的数据（只对 keep-source 开启有效）
     * @type: Promise
     * @param {Row | Array<Row>} rows:
     * @param {string} field?:
     * @return {Promise}
     */
    revertData(rows, field) {
      return this.$refs.editable.revertData(rows, field);
    },

    /**
     * @name: remove
     * @description: 删除指定行数据（不支持深层结构），指定 row 或 [row, ...] 删除多条数据，如果为空则删除所有数据
     * @type: Promise
     * @param {Row | Array<Row>} rows
     * @return {Promise} {Row, array<Row>}
     */
    remove(rows) {
      return this.$refs.editable.remove(rows);
    },

    /**
     * @name: removeSelecteds
     * @description: 删除单选框或多选框选中的行数据（不支持深层结构）
     * @type: Promise
     * @return {Promise} {Row, array<Row>}
     */
    removeSelecteds() {
      if (this.selectType == "radio") {
        return this.$refs.editable.removeRadioRow();
      } else if (this.selectType == "checkbox") {
        return this.$refs.editable.removeCheckboxRow();
      }
    },

    /**
     * @name: getRowIndex
     * @description: 根据 row 获取索引
     * @type: Function
     * @param {Row} row 行数据
     * @param {string} scope? : 获取范围 不传：相对于data中的 | "current"：相对于当前数据 | "virtual"：渲染中的虚拟索引
     * @return {number} 返回索引，返回 -1 代表没找到
     */
    getRowIndex(row, scope) {
      if (scope == "current") {
        return this.$refs.editable._getRowIndex(row);
      } else if (scope == "virtual") {
        return this.$refs.editable.$getRowIndex(row);
      } else {
        return this.$refs.editable.getRowIndex(row);
      }
    },

    /**
     * @name: getColumns
     * @description: 根据索引获取表格的可视列
     * @type: Function
     * @param {number} columnIndex: 索引
     * @return {object}
     */
    getColumns(columnIndex) {
      return this.$refs.editable.getColumns(columnIndex);
    },

    /**
     * @name: getTableColumn
     * @description: 获取当前表格的列
     * @type: Function
     * @return {object} {collectColumn, fullColumn, visibleColumn, tableColumn}
     */
    getTableColumn() {
      // {collectColumn, fullColumn, visibleColumn, tableColumn}
      // { 收集到的全量列、全量表头列、处理条件之后的全量表头列、当前渲染中的表头列 }
      return this.$refs.editable.getTableColumn();
    },

    /**
     * @name: getColid
     * @description: 根据列获取列的唯一主键
     * @type: Function
     * @param {ColumnConfig} column
     * @return {string} 列的唯一主键
     */
    getColid(column) {
      return this.$refs.editable.getColid(column);
    },

    /**
     * @name: getColumnById
     * @description: 根据列的唯一主键获取列
     * @type: Function
     * @param {string} colid: 列的唯一主键
     * @return {Column}
     */
    getColumnById(colid) {
      return this.$refs.editable.getColumnById(colid);
    },

    /**
     * @name: getColumnByField
     * @description: 根据列的字段名获取列
     * @type: Function
     * @param {string}
     * @return {Column}
     */
    getColumnByField(field) {
      return this.$refs.editable.getColumnByField(field);
    },

    /**
     * @name: getColumnIndex
     * @description: 根据 column 获取索引
     * @type: Function
     * @param {Column} column
     * @param {Column} scope? : 获取范围，不传：相对于columns | "current"：相对于当前表格列（分组表头可能会用到 | "virtual"：获取渲染中的虚拟索引
     * @return {number}
     */
    getColumnIndex(column, scope) {
      if (scope == "current") {
        return this.$refs.editable._getColumnIndex(column);
      } else if (scope == "virtual") {
        return this.$refs.editable.$getColumnIndex(column);
      } else {
        return this.$refs.editable.getColumnIndex(column);
      }
    },

    /**
     * @name: getRowById
     * @description: 根据行的唯一主键获取行
     * @type: Function
     * @param {string} rowid
     * @return {object}
     */
    getRowById(rowid) {
      return this.$refs.editable.getRowById(rowid);
    },

    getRowByIndex(idxs) {
      if (idxs) {
        if (typeof idxs === "number") {
          return this.tableData[idxs];
        } else if (Array.isArray(idxs)) {
          return idxs.map(item => this.tableData[item]);
        }
      } else {
        return [];
      }
    },

    /**
     * @name: getRowid
     * @description: 根据行获取行的唯一主键
     * @type: Function
     * @param {object} row
     * @return {string }
     */
    getRowid(row) {
      return this.$refs.editable.getRowid(row);
    },

    /**
     * @name: getTableData
     * @description: 获取当前表格的数据
     * @type: Function
     * @return {object} {fullData, visibleData, tableData, footerData}
     */
    getTableData() {
      // {fullData, visibleData, tableData, footerData}
      // {完整的全量表体数据、处理条件之后的全量表体数据、当前渲染中的表体数据、当前渲染中的表尾数据 }
      return this.$refs.editable.getTableData();
    },

    /**
     * @name: getRecordset
     * @description: 获取表格数据集
     * @type: Function
     * @return {object} {insertRecords, removeRecords, updateRecords}
     */
    getRecordset() {
      // {insertRecords, removeRecords, updateRecords}
      // {插入的数据，删除的数据，更改的数据}
      return this.$refs.editable.getRecordset();
    },

    /**
     * @name: getScroll
     * @description: 获取表格的滚动状态
     * @type: Function
     * @return {object} {virtualX, virtualY, scrollTop, scrollLeft}
     */
    getScroll() {
      return this.$refs.editable.getScroll();
    },

    /**
     * @name: clearSort
     * @description: 手动清空排序条件
     * @type: Promise
     * @return {Promise}
     */
    clearSort() {
      return this.$refs.editable.clearSort();
    },

    /**
     * @name: clearFilter
     * @description: 手动清空筛选条件（如果不传 column 则清空所有筛选条件）
     * @type: Promise
     * @param {ColumnConfig} column
     * @return {Promise}
     */
    clearFilter(column) {
      return this.$refs.editable.clearFilter(column);
    },

    /**
     * @name: clearData
     * @description: 手动清空单元格内容，如果不创参数，则清空整个表格内容，如果传了行则清空指定行内容，如果传了指定字段，则清空该字段内容
     * @type: Promise
     * @param {Row | array<Row>} rows
     * @param {string} field?: 列字段
     * @return {Promise}
     */
    clearData(rows, field) {
      return this.$refs.editable.clearData(rows, field);
    },

    /**
     * @name: clearValidate
     * @description: 手动清除校验
     * @type: Promise
     * @return {Promise}
     */
    clearValidate() {
      return this.$refs.editable.clearValidate();
    },

    /**
     * @name: clearAll
     * @description: 手动清除表格所有条件，还原到初始状态（对于增删改查的场景中可能会用到，比如在数据保存之后清除表格缓存）
     * @type: Promise
     * @return {Promise}
     */
    clearAll() {
      return this.$refs.editable.clearAll();
    },

    /**
     * @name: updateFooter
     * @description: 手动更新表尾（对于某些需要频繁更新的场景下可能会用到）
     * @type: Promise
     * @return {Promise}
     */
    updateFooter() {
      return this.$refs.editable.updateFooter();
    },

    /**
     * @name: setColumnVisible
     * @description: 设置指定列的 显示/隐藏
     * @type: Promise
     * @param {ColumnConfig} column
     * @param {string} visible?: "hide" | "show"， 默认"hide"
     * @return {Promise}
     */
    setColumnVisible(column, visible = "hide") {
      if (visible == "hide") {
        return this.$refs.editable.hideColumn(column);
      } else if (visible == "show") {
        return this.$refs.editable.showColumn(column);
      }
    },

    /**
     * @name: scrollToRow
     * @description: 如果有滚动条，则滚动到对应的行（对于某些特定的场景可能会用到，比如定位到某一行）
     * @type: Promise
     * @param {Row} row
     * @return {Promise}
     */
    scrollToRow(row) {
      return this.$refs.editable.scrollToRow(row);
    },

    /**
     * @name: scrollToColumn
     * @description: 如果有滚动条，则滚动到对应的列（对于某些特定的场景可能会用到，比如定位到某一列）
     * @type: Promise
     * @param {ColumnConfig} column
     * @return {Promise}
     */
    scrollToColumn(column) {
      return this.$refs.editable.scrollToColumn(column);
    },

    /**
     * @name: validate
     * @description: 表格校验函数，如果指定 row 或 rows 则校验指定一行或多行，否则校验整个表格。该回调函数会在校验结束后被调用 callback(errMap)。若不传入回调函数，则会返回一个 promise
     * @type: Promise<ErrMap>
     * @param {Row | array<Row>} rows?
     * @param {function} callback?
     * @return {Promise<ErrMap>}
     */
    validate(rows, callback) {
      return this.$refs.editable.validate(rows, callback);
    },

    /**
     * @name: fullValidate
     * @description: 表格完整校验函数，和 validate 的区别就是会对全量数据的所有规则进行完整校验
     * @type: Promise<ErrMap>
     * @param {Row | array<Row>} rows?
     * @param {function} callback?
     * @return {Promise<ErrMap>}
     */
    fullValidate(rows, callback) {
      return this.$refs.editable.fullValidate(rows, callback);
    },

    /**
     * @name: recalculate
     * @description: 重新计算表格，如果传 true 则进行完整计算（对于某些特殊场景可能会用到，比如隐藏的表格、重新计算列宽...等）
     * @type: Promise
     * @param {boolean} refull?
     * @return {Promise}
     */
    recalculate(refull) {
      return this.$refs.editable.recalculate(refull);
    },

    /**
     * @name: setFilter
     * @description: 用于 filters，修改筛选列表（在筛选条件更新之后可以调用 updateData 函数处理表格数据）
     * @type: Promise
     * @param {Column} column
     * @param {array} options
     * @return {Promise}
     */
    setFilter(column, options) {
      return this.$refs.editable.setFilter(column, options);
    },

    /* ----------------------- Radio and Checkbox ------------------------- */

    /**
     * @name: getCurrentRecord
     * @description: 用于 highlight-current-row，获取高亮的当前行数据
     * @type: Function
     * @return {Row}
     */
    getCurrentRecord() {
      return this.$refs.editable.getCurrentRecord();
    },

    /**
     * @name: getSelectRecords
     * @description: 获取单选或多选选中行的数据
     * @type: Function
     * @return {Row | array<Row>} 多选时返回 array，单选时返回 object
     */
    getSelectRecords() {
      if (this.selectType == "radio") {
        return this.$refs.editable.getRadioRecord();
      } else if (this.selectType == "checkbox") {
        return this.$refs.editable.getCheckboxRecords();
      }
    },

    /**
     * @name: getSelectReserveRecords
     * @description: 用于 checkbox-config.reserve 和 radio-config.reserve，获取已保留选中的行数据（不包含当前列表)
     * @type: Function
     * @return {Row | array<Row>} 选时返回 array，单选时返回 object
     */
    getSelectReserveRecords() {
      if (this.selectType == "radio") {
        return this.$refs.editable.getRadioReserveRecord();
      } else if (this.selectType == "checkbox") {
        return this.$refs.editable.getCheckboxReserveRecords();
      }
    },

    /**
     * @name: getCheckboxIndeterminateRecords
     * @description: 用于 type=checkbox，获取半选状态的行数据
     * @type: Function
     * @return {array<Row>}
     */
    getCheckboxIndeterminateRecords() {
      return this.$refs.editable.getCheckboxIndeterminateRecords();
    },

    /**
     * @name: setCurrentRow
     * @description: 用于 highlight-current-row，设置某一行为高亮状态
     * @type: Promise
     * @param {Row} row
     * @return {Promise}
     */
    setCurrentRow(row) {
      return this.$refs.editable.setCurrentRow(row);
    },

    /**
     * @name: setCurrentColumn
     * @description: 用于 highlight-current-column，设置某列行为高亮状态
     * @type: Promise
     * @param {ColumnConfig} column
     * @return {Promise}
     */
    setCurrentColumn(column) {
      return this.$refs.editable.setCurrentColumn(column);
    },

    /**
     * @name: setSelectedRows
     * @description: 设置 单选行/多选行 的选中状态
     * @type: Promise
     * @param {Row | array<Row>} rows
     * @param {boolean} checked?: 多选时默认 true
     * @return {Promise}
     */
    setSelectedRows(rows, checked = true) {
      if (this.selectType == "radio") {
        const row = Array.isArray(rows) ? rows[0] : rows;
        return this.$refs.editable.setRadioRow(row);
      } else if (this.selectType == "checkbox") {
        return this.$refs.editable.setCheckboxRow(rows, checked);
      }
    },

    /**
     * @name: setSelectedRow
     * @description: 根据索引设置 单选行 / 多选行 的选中状态，有scope局限性
     * @type: Function
     * @param {array} rowsIdx: 索引集合
     * @param {boolean} checked?: 多选时默认 true
     * @return {Promise}
     */
    setSelectedRow(rowsIdx, checked = true) {
      if (rowsIdx.length > 0) {
        if (this.selectType == "radio") {
          let idx = rowsIdx[0];
          return this.$refs.editable.setRadioRow(this.tableData[idx]);
        } else if (this.selectType == "checkbox") {
          return this.$refs.editable.setCheckboxRow(
            rowsIdx.map(i => this.tableData[i]),
            checked
          );
        }
      }
    },

    /**
     * @name: setAllCheckboxRow
     * @description: 用于 type=checkbox，设置所有行的选中状态
     * @type: Promise
     * @param {boolean} checked
     * @return {Promise}
     */
    setAllCheckboxRow(checked) {
      return this.$refs.editable.setAllCheckboxRow(checked);
    },

    /**
     * @name: clearCurrentRow
     * @description: 用于 highlight-current-row，手动清空当前高亮的状态
     * @type: Promise
     * @return {Promise}
     */
    clearCurrentRow() {
      return this.$refs.editable.clearCurrentRow();
    },

    /**
     * @name: clearCurrentColumn
     * @description: 用于 highlight-current-column，手动清空当前高亮的状态
     * @type: Promise
     * @return {Promise}
     */
    clearCurrentColumn() {
      return this.$refs.editable.clearCurrentColumn();
    },

    /**
     * @name: clearSelect
     * @description: 手动清空 单选/多选 的选择
     * @type: Promise
     * @return {Promise}
     */
    clearSelect() {
      if (this.selectType == "radio") {
        return this.$refs.editable.clearRadioRow();
      } else if (this.selectType == "checkbox") {
        return this.$refs.editable.clearCheckboxRow();
      }
    },

    /**
     * @name: clearCheckboxReserve
     * @description: 用于 checkbox-config.reserve，手动清空用户保留选中的行数据
     * @type: Promise
     * @return {Promise}
     */
    clearCheckboxReserve() {
      return this.$refs.editable.clearCheckboxReserve();
    },

    /**
     * @name: isSelectedByRow
     * @description: 判断 某复选/单选行 是否勾选
     * @type: Function
     * @param {Row} row
     * @return {boolean}
     */
    isSelectedByRow(row) {
      if (this.selectType == "radio") {
        return this.$refs.editable.isCheckedByRadioRow(row);
      } else if (this.selectType == "checkbox") {
        return this.$refs.editable.getCheckboxReserveRecords();
      }
    },

    /* ----------------------------- Edit ------------------------------ */

    /**
     * @name: setActiveCell
     * @description: 用于 edit-config，激活单元格编辑
     * @type: Promise
     * @param {Row} row
     * @param {string} field: 列字段
     * @return {Promise}
     */
    setActiveCell(row, field) {
      return this.$refs.editable.setActiveCell(row, field);
    },

    /**
     * @name: isInsertByRow
     * @description: 用于 edit-config，判断行是否为插入的临时数据
     * @type: Function
     * @param {Row} row: 行数据
     * @return {boolean}
     */
    isInsertByRow(row) {
      return this.$refs.editable.isInsertByRow(row);
    },

    /**
     * @name: isUpdateByRow
     * @description: 只对 keep-source 开启有效，判断行数据是否发生改变
     * @type: Function
     * @param {Row} row
     * @param {string} field?: 列字段
     * @return {boolean}
     */
    isUpdateByRow(row, field) {
      return this.$refs.editable.isUpdateByRow(row, field);
    },

    /* ----------------------------- Expand ------------------------------ */

    /**
     * @name: getRowExpandRecords
     * @description: 用于 expand-config，用于展开行，获取已展开的行数据
     * @type: Function
     * @return {array<Row>}
     */
    getRowExpandRecords() {
      return this.$refs.editable.getRowExpandRecords();
    },

    /**
     * @name: setRowExpand
     * @description: 用于 expand-config，设置展开行，第二个参数设置这一行展开与否
     * @type: Promise
     * @param {Row | array<Row>} rows
     * @param {boolean} checked
     * @return {Promise}
     */
    setRowExpand(rows, checked) {
      return this.$refs.editable.setRowExpand(rows, checked);
    },

    /**
     * @name: setAllRowExpand
     * @description: 用于 expand-config，设置所有行的展开与否（如果是关闭所有行，可以使用 clearRowExpand 快速清除）
     * @type: Promise
     * @param {boolean} checked
     * @return {Promise}
     */
    setAllRowExpand(checked) {
      return this.$refs.editable.setAllRowExpand(checked);
    },

    /**
     * @name: clearRowExpand
     * @description: 用于 type=expand，手动清空展开行状态，数据会恢复成未展开的状态
     * @type: Promise
     * @return {Promise}
     */
    clearRowExpand() {
      return this.$refs.editable.clearRowExpand();
    },

    /* ----------------------------- Tree ------------------------------ */

    /**
     * @name: getTreeExpandRecords
     * @description: 用于 tree-config，用于树表格，获取已展开的节点（注意，即使父节点被收起，只要该节点还处于展开状态都能获取到）
     * @type: Function
     * @return {array<Row>}
     */
    getTreeExpandRecords() {
      return this.$refs.editable.getTreeExpandRecords();
    },

    /**
     * @name: setTreeExpand
     * @description: 用于 tree-config，设置展开树形节点，二个参数设置这一行展开与否
     * @type: Promise
     * @param {Row | array<Row>} rows
     * @param {boolean} checked
     * @return {Promise}
     */
    setTreeExpand(rows, checked) {
      return this.$refs.editable.setTreeExpand(rows, checked);
    },

    /**
     * @name: setAllTreeExpand
     * @description: 用于 tree-config，设置所有树节点的展开与否（如果是关闭所有树节点，可以使用 clearTreeExpand 快速清除）
     * @type: Promise
     * @param {boolean} checked
     * @return {Promise}
     */
    setAllTreeExpand(checked) {
      return this.$refs.editable.setAllTreeExpand(checked);
    },

    /**
     * @name: clearTreeExpand
     * @description: 用于 tree-config，手动清空树形节点的展开状态，数据会恢复成未展开的状态
     * @type: Promise
     * @return {Promise}
     */
    clearTreeExpand() {
      return this.$refs.editable.clearTreeExpand();
    }
  }
};
